namespace JoinBox.MathEx;

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Text;

/*
 * 泛型中无法约束操作四则运算,而实现一个约束类感觉会降低速度 https://www.helloworld.net/p/2609830207
 * 
 * 矩阵乘法 https://www.bilibili.com/video/BV1QU4y1V7PJ?from=search&seid=4674962908957462089
 * 矩阵转置 https://www.bilibili.com/video/BV1jh411e7Vb?from=search&seid=4674962908957462089
 * 矩阵求逆 https://www.bilibili.com/video/BV1iE411w7vt
 * 微软:验证矩阵求逆 https://docs.microsoft.com/zh-cn/archive/msdn-magazine/2016/july/test-run-matrix-inversion-using-csharp
 * 本代码来自 https://www.cnblogs.com/wzxwhd/p/5877624.html
 *
 * 这里最好不要并行,因为我测试了它慢了很多
 * 
 * 不知道c#并行库和英特尔TBB并行库是不是一样的,我们假设它就是一个
 * 那么 双Parallel.For 需要加锁,
 * 主要是因为 双并行 会根据 工作窃取法 进行分配任务,完成任务的线程会抓其他线程过来
 * https://docs.microsoft.com/zh-cn/dotnet/standard/parallel-programming/how-to-write-a-simple-parallel-for-loop
 * 访问小型循环
 * https://docs.microsoft.com/zh-cn/dotnet/standard/parallel-programming/how-to-speed-up-small-loop-bodies
*/


[Serializable]
[StructLayout(LayoutKind.Sequential)]
[DebuggerDisplay("{DebuggerDisplay,nq}")]
[DebuggerTypeProxy(typeof(Matrix))]
public class Matrix : IFormattable, IEquatable<Matrix>
{
    [DebuggerBrowsable(DebuggerBrowsableState.Never)]
    private string DebuggerDisplay => ToString("f4");

    #region 成员
#pragma warning disable IDE0044 // 添加只读修饰符
    /// <summary>
    /// 用一维储存数组(扁平化)
    /// </summary>
    double[] _element;
    /// <summary>
    /// 获取矩阵行数
    /// </summary>
    public int Rows => _Rows;
    /// <summary>
    /// 行
    /// </summary>
    int _Rows;
    /// <summary>
    /// 获取矩阵列数
    /// </summary>
    public int Cols => _Cols;
    /// <summary>
    /// 列
    /// </summary>
    int _Cols;
#pragma warning restore IDE0044 // 添加只读修饰符
    #endregion

    #region 构造
    /// <summary>
    /// 矩阵
    /// </summary>
    /// <param name="rowsNum">行</param>
    /// <param name="colsNum">列</param>
    public Matrix(int rowsNum, int colsNum = 1)
    {
        if (rowsNum <= 0)
            throw new ArgumentNullException(nameof(rowsNum));
        if (colsNum <= 0)
            throw new ArgumentNullException(nameof(colsNum));

        _Rows = rowsNum;
        _Cols = colsNum;
        if (_Cols <= 1)
        {
            _Cols = 1;
            _element = new double[_Rows];
        }
        else
        {
            _element = new double[_Rows * _Cols];
        }
    }
    /// <summary>
    /// 矩阵
    /// </summary>
    /// <param name="oldMatrix">用来克隆</param>
    public Matrix(Matrix oldMatrix)
    {
        _Cols = oldMatrix._Cols;
        _Rows = oldMatrix._Rows;
        _element = new double[oldMatrix._element.Length];
        oldMatrix._element.CopyTo(_element, 0);
        // var arr = new int[] { 1, 2, 3 };
        // var arr2 =new int[arr.Length];
        // arr.CopyTo(arr2,0);
    }
    /// <summary>
    /// 矩阵
    /// </summary>
    /// <param name="m">二维数组</param>
    public Matrix(double[][] m)
    {
        _Rows = m.Length;
        if (_Rows <= 0)
            throw new ArgumentException("矩阵参数行为0");

        _Cols = m[0].Length;
        if (_Cols <= 0)
            throw new ArgumentException("矩阵参数列为0");

        // 矩阵扁平化,更好的索引速度
        _element = new double[_Rows * _Cols];
#if 永不执行___NET35
        Parallel.For(0, _Rows, i => {
            Parallel.For(0, _Cols, j => {
                _element[i * _Cols + j] = m[i][j];
            });
        });
#else
        for (int i = 0; i < _Rows; i++)
            for (int j = 0; j < _Cols; j++)
                _element[i * _Cols + j] = m[i][j];
#endif
    }
    /// <summary>
    /// 矩阵
    /// </summary>
    /// <param name="m">二维数组</param>
    public Matrix(double[,] m)
    {
        _Rows = m.GetLength(0);
        _Cols = m.GetLength(1);

        if (_Rows <= 0)
            throw new ArgumentException("矩阵参数行为0");
        if (_Cols <= 0)
            throw new ArgumentException("矩阵参数列为0");

        // 矩阵扁平化,更好的索引速度
        _element = new double[_Rows * _Cols];
#if 永不执行___NET35
        Parallel.For(0, _Rows, i => {
            Parallel.For(0, _Cols, j => {
                _element[i * _Cols + j] = m[i, j];
            });
        });
#else
        for (int i = 0; i < _Rows; i++)
            for (int j = 0; j < _Cols; j++)
                _element[i * _Cols + j] = m[i, j];
#endif
    }
    /// <summary>
    /// 矩阵
    /// </summary>
    /// <param name="m">二维数组</param>
    public Matrix(List<List<double>> m)
    {
        _Rows = m.Count;
        if (_Rows <= 0)
            throw new ArgumentException("矩阵参数行为0");

        _Cols = m[0].Count;
        if (_Cols <= 0)
            throw new ArgumentException("矩阵参数列为0");

        // 矩阵扁平化,更好的索引速度
        _element = new double[_Rows * _Cols];
#if 永不执行___NET35
        Parallel.For(0, _Rows, i => {
            Parallel.For(0, _Cols, j => {
                _element[i * _Cols + j] = m[i][j];
            });
        });
#else
        for (int i = 0; i < _Rows; i++)
            for (int j = 0; j < _Cols; j++)
                _element[i * _Cols + j] = m[i][j];
#endif
    }
    /// <summary>
    /// 矩阵
    /// </summary>
    /// <param name="m">此数组生命周期将被矩阵延长</param>
    public Matrix(double[] m)
    {
        _Rows = m.Length;
        _Cols = 1;
        _element = m;
    }
    #endregion

    #region 重载运算符
    /// <summary>
    /// 矩阵绝对值
    /// </summary>
    public static Matrix Abs(Matrix oldMatrix)
    {
        var result = oldMatrix.Clone();
#if 永不执行___NET35
        Parallel.For(0, oldMatrix._element.Length, i => {
            result._element[i] = Math.Abs(oldMatrix._element[i]);
        });
#else
        for (int i = 0; i < oldMatrix._element.Length; i++)
            result._element[i] = System.Math.Abs(oldMatrix._element[i]);
#endif
        return result;
    }
    /// <summary>
    /// 矩阵相加
    /// </summary>
    /// <param name="a">第一个矩阵</param>
    /// <param name="b">第二个矩阵,大小要和第一个矩阵相同</param>
    /// <returns>返回矩阵相加后的结果</returns>
    public static Matrix operator +(Matrix a, Matrix b)
    {
        if (a._Cols != b._Cols || a._Rows != b._Rows)
            throw new Exception("两个矩阵行列不相等");

        var res = a.Clone();
#if 永不执行___NET35
        Parallel.For(0, a._element.Length, i => {
            res._element[i] = a._element[i] + b._element[i];
        });
#else
        for (int i = 0; i < a._element.Length; i++)
            res._element[i] = a._element[i] + b._element[i];
#endif
        return res;
    }

    /// <summary>
    /// 矩阵相减
    /// </summary>
    /// <param name="a">第一个矩阵</param>
    /// <param name="b">第二个矩阵,大小要和第一个矩阵相同</param>
    /// <returns>返回矩阵相减后的结果</returns>
    public static Matrix operator -(Matrix a, Matrix b)
    {
        if (a._Cols != b._Cols || a._Rows != b._Rows)
            throw new Exception("两个矩阵行列不相等");

        var res = a.Clone();
#if 永不执行___NET35
        Parallel.For(0, a._element.Length, i => {
            res._element[i] = a._element[i] - b._element[i];
        });
#else
        for (int i = 0; i < a._element.Length; i++)
            res._element[i] = a._element[i] - b._element[i];
#endif
        return res;
    }
    /// <summary>
    /// 对矩阵每个元素取相反数
    /// </summary>
    /// <param name="a">矩阵</param>
    /// <returns>相反数矩阵</returns>
    public static Matrix operator -(Matrix a)
    {
        var res = a.Clone();
#if 永不执行___NET35
        Parallel.For(0, a._element.Length, i => {
            res._element[i] = -a._element[i];
        });
#else
        for (int i = 0; i < a._element.Length; i++)
            res._element[i] = -a._element[i];
#endif
        return res;
    }

    /// <summary>
    /// 矩阵相乘
    /// </summary>
    /// <param name="a">第一个矩阵</param>
    /// <param name="b">第二个矩阵,这个矩阵的行要与第一个矩阵的列相等</param>
    /// <returns>返回相乘后的一个新的矩阵</returns>
    public static Matrix operator *(Matrix a, Matrix b)
    {
        if (a._Cols != b._Rows)
            throw new Exception("两个矩阵行和列不等");

        var res = new Matrix(a.Rows, b.Cols);// 这个是不扁平化的初始化
#if 永不执行___NET35
        Parallel.For(0, a.Rows, i => {
            Parallel.For(0, b.Cols, j => {
                Parallel.For(0, a.Cols, k => {
                    res._element[i * b.Cols + j]
                    += a._element[i * a.Cols + k] * b._element[k * b.Cols + j];
                });
            });
        });
#else

        for (int i = 0; i < a.Rows; i++)
            for (int j = 0; j < b.Cols; j++)
                for (int k = 0; k < a.Cols; k++)
                    res._element[i * b.Cols + j]
                        += a._element[i * a.Cols + k] * b._element[k * b.Cols + j];
#endif

        return res;
    }

    /// <summary>
    /// 数乘
    /// </summary>
    /// <param name="a">矩阵</param>
    /// <param name="scale">缩放比例</param>
    /// <returns>返回相乘后的新的矩阵</returns>
    public static Matrix operator *(Matrix a, double scale)
    {
        var res = a.Clone();
#if 永不执行___NET35
        Parallel.For(0, a._element.Length, i => {
            res._element[i] = a._element[i] * scale;
        });
#else
        for (int i = 0; i < a._element.Length; i++)
            res._element[i] = a._element[i] * scale;
#endif
        return res;
    }
    /// <summary>
    /// 数除
    /// </summary>
    /// <param name="a">矩阵</param>
    /// <param name="scale">缩放比例</param>
    /// <returns></returns>
    public static Matrix operator /(Matrix a, double scale)
    {
        var res = a.Clone();
#if 永不执行___NET35
        Parallel.For(0, a._element.Length, i => {
            res._element[i] = a._element[i] / scale;
        });
#else
        for (int i = 0; i < a._element.Length; i++)
            res._element[i] = a._element[i] / scale;
#endif
        return res;
    }
    #endregion

    #region 重载运算符_比较
    public override bool Equals(object? obj)
    {
        return this.Equals(obj as Matrix);
    }
    public bool Equals(Matrix? other)
    {
        return this == other;// 此处不需要模糊比较
    }
    public static bool operator !=(Matrix? a, Matrix? b)
    {
        return !(a == b);
    }
    public static bool operator ==(Matrix? a, Matrix? b)
    {
        // 此处地方不允许使用==null,因为此处是定义
        if (b is null)
            return a is null;
        else if (a is null)
            return false;
        if (ReferenceEquals(a, b))// 同一对象
            return true;

        if (a._Cols != b._Cols || a._Rows != b._Rows)
            return false;


        bool flag = true;
#if 永不执行___NET35
        Parallel.For(0, a._element.Length, (i, po) => {
            if (a._element[i] != b._element[i])
            {
                flag = false;
                po.Stop();
            }
        });
#else
        for (int i = 0; i < a._element.Length; i++)
            if (a._element[i] != b._element[i])
            {
                flag = false;
                break;
            }
#endif
        return flag;
    }
    public override int GetHashCode()
    {
#if CAD
        return (_Cols, _Rows).GetHashCode() ^ _element.GetHashCode(); 
#else
        return _Cols.GetHashCode() << 5 + _Cols ^ _Rows.GetHashCode() ^ _element.GetHashCode();
#endif
    }
    #endregion

    #region 矩阵运算特性
    /// <summary>
    /// 相当于是矩阵的除法
    /// A*X=B,已知A,B求X.
    /// </summary>
    /// <param name="b"></param>
    /// <returns></returns>
    public Matrix Solve(Matrix b)
    {
        if (_Cols != _Rows || Determinant() == 0)
            throw new Exception("矩阵不是方阵无法运算");

        return Inverse() * b;
    }
    /// <summary>
    /// 矩阵转置
    /// </summary>
    /// <returns>返回当前矩阵转置后的新矩阵</returns>
    public Matrix Transpose()
    {
        // 转置交换:列*行 
        var res = new Matrix(_Cols, _Rows);
#if 永不执行___NET35
        Parallel.For(0, _Cols, j => {
            Parallel.For(0, _Rows, i => {
                res._element[j * _Rows + i] = _element[i * _Cols + j];
            });
        });
#else
        for (int j = 0; j < _Cols; j++)
            for (int i = 0; i < _Rows; i++)
                res._element[j * _Rows + i] = _element[i * _Cols + j];
#endif
        return res;
    }
    /// <summary>
    /// 矩阵求逆
    /// </summary>
    /// <returns>返回求逆后的新的矩阵</returns>
    public Matrix Inverse()
    {
        if (_Cols != _Rows || Determinant() == 0)
            throw new Exception("矩阵不是方阵无法求逆");

        // 初始化一个同等大小的单位阵
        var unityEmat = EMatrix();
        // 克隆保证原始矩阵不变
        var clone = Clone();
        for (int i1 = 0; i1 < _Rows; i1++)
        {
            // 首先找到第i列的绝对值最大的数,并将该行和第i行互换
            int rowMax = i1;
            double max = System.Math.Abs(clone._element[i1 * _Cols + i1]);
            for (int i2 = i1; i2 < _Rows; i2++)
            {
                var tmp = System.Math.Abs(clone._element[i2 * _Cols + i1]);
                if (tmp > max)
                {
                    rowMax = i2;
                    max = tmp;
                }
            }

            // 将第i行和找到最大数那一行rowMax交换
            if (rowMax != i1)
            {
                clone.Exchange(i1, rowMax);
                unityEmat.Exchange(i1, rowMax);
            }
            // 将第i行做初等行变换,将第一个非0元素化为1
            double r = 1.0 / clone._element[i1 * _Cols + i1];
            clone.Exchange(i1, -1, r);
            unityEmat.Exchange(i1, -1, r);

            // 消元
            for (int i3 = 0; i3 < _Rows; i3++)
            {
                // 到本行后跳过
                if (i3 == i1)
                    continue;
                r = -clone._element[i3 * _Cols + i1];
                clone.Exchange(i1, i3, r);
                unityEmat.Exchange(i1, i3, r);
            }
        }
        return unityEmat;
    }
    /// <summary>
    /// 行列式
    /// </summary>
    /// <returns></returns>
    public double Determinant()
    {
        if (_Cols != _Rows)
            throw new Exception("数量不等同,不是行列式");

        var ret = Clone();
        // 行列式每次交换行,都需要乘以-1
        double res = 1;
        for (int i1 = 0; i1 < _Rows; i1++)
        {
            // 首先找到第i列的绝对值最大的数
            int rowMax = i1;
            double max = System.Math.Abs(ret._element[i1 * _Cols + i1]);
            for (int i2 = i1; i2 < _Rows; i2++)
            {
                var tmp = System.Math.Abs(ret._element[i2 * _Cols + i1]);
                if (tmp > max)
                {
                    rowMax = i2;
                    max = tmp;
                }
            }
            // 将第i行和找到最大数那一行rowMax交换,同时将单位阵做相同初等变换
            if (rowMax != i1)
            {
                ret.Exchange(i1, rowMax);
                res *= -1;
            }
            // 消元
            for (int i3 = i1 + 1; i3 < _Rows; i3++)
            {
                double r = -ret._element[i3 * _Cols + i1] / ret._element[i1 * _Cols + i1];
                ret.Exchange(i1, i3, r);
            }
        }
        // 此处不允许并行,res线程不安全,需要加锁更慢
        // 计算对角线乘积
        for (int i = 0; i < _Rows; i++)
            res *= ret._element[i * _Cols + i];

        return res;
    }
    /// <summary>
    /// 初等变换：行交换
    /// </summary>
    /// <param name="r1">第r1行</param>
    /// <param name="r2">第r2行</param>
    public void Exchange(int r1, int r2)
    {
        if (System.Math.Min(r2, r1) < 0 || System.Math.Max(r1, r2) >= _Rows)
            throw new Exception("超出索引");
#if 永不执行___NET35
        Parallel.For(0, _Cols, j => {
            var temp = _element[r1 * _Cols + j];
            _element[r1 * _Cols + j] = _element[r2 * _Cols + j];
            _element[r2 * _Cols + j] = temp;
        });
#else
        for (int j = 0; j < _Cols; j++)
        {
#pragma warning disable IDE0180 // 使用元组交换值
            var temp = _element[r1 * _Cols + j];
            _element[r1 * _Cols + j] = _element[r2 * _Cols + j];
            _element[r2 * _Cols + j] = temp;
#pragma warning restore IDE0180 // 使用元组交换值
        }
#endif
    }
    /// <summary>
    /// 初等变换：将r1行乘以某个数加到r2行
    /// </summary>
    /// <param name="r1">第r1行乘num</param>
    /// <param name="r2">加到第r2行,若第r2行为负,则直接将r1乘以num并返回</param>
    /// <param name="scale">缩放比例</param>
    public void Exchange(int r1, int r2, double scale)
    {
        if (System.Math.Min(r1, r2) >= 0 && System.Math.Max(r1, r2) < _Rows)
        {
#if 永不执行___NET35
            Parallel.For(0, _Cols, j => {
                _element[r2 * _Cols + j] += _element[r1 * _Cols + j] * scale;
            });
#else
            for (int j = 0; j < _Cols; j++)
                _element[r2 * _Cols + j] += _element[r1 * _Cols + j] * scale;
#endif
        }
        else if (r2 < 0)
        {
#if 永不执行___NET35
            Parallel.For(0, _Cols, j => {
                _element[r1 * _Cols + j] *= scale;
            });
#else
            for (int j = 0; j < _Cols; j++)
                _element[r1 * _Cols + j] *= scale;
#endif
        }
        else
            throw new Exception("超出索引");
    }
    /// <summary>
    /// 得到一个同等大小的单位矩阵
    /// </summary>
    /// <returns></returns>
    public Matrix EMatrix()
    {
        if (_Rows != _Cols)
            throw new Exception("不是方阵,无法得到单位矩阵");

        var res = new Matrix(_Rows, _Cols);// 没有扁平化的初始化
#if 永不执行___NET35
        Parallel.For(0, _Rows, i => {
            Parallel.For(0, _Cols, j => {
                if (i == j)
                    res._element[i * _Cols + j] = 1;
                else
                    res._element[i * _Cols + j] = 0;
            });
        });
#else
        for (int i = 0; i < _Rows; i++)
            for (int j = 0; j < _Cols; j++)
                if (i == j)
                    res._element[i * _Cols + j] = 1;
                else
                    res._element[i * _Cols + j] = 0;
#endif
        return res;
    }
    #endregion

    #region 索引器(提供外部访问)
    /// <summary>
    /// 索引器:第i行第j列的元素值
    /// </summary>
    /// <param name="rows">行</param>
    /// <param name="cols">列</param>
    /// <returns>返回第i行第j列的元素值</returns>
    public double this[int rows, int cols]
    {
        get
        {
            if (rows < _Rows && cols < _Cols)
                return _element[rows * _Cols + cols];
            else
                throw new Exception("索引越界");
        }
        set => _element[rows * _Cols + cols] = value;
    }
    #endregion

    #region 方法
    /// <summary>
    /// 设置行数据
    /// </summary>
    /// <param name="row">行</param>
    /// <param name="data">数据</param>
    public void SetRow(int row, double[] data)
    {
#if 永不执行___NET35
        Parallel.For(0, data.Length, j => {
            _element[row * _Cols + j] = data[j];
        });
#else
        for (int j = 0; j < data.Length; j++)
            _element[row * _Cols + j] = data[j];
#endif
    }

    /// <summary>
    /// 设置列数据
    /// </summary>
    /// <param name="col">列</param>
    /// <param name="data">数据</param>
    public void SetCol(int col, double[] data)
    {
#if 永不执行___NET35
        Parallel.For(0, data.Length, i => {
            _element[i * _Cols + col] = data[i];
        });
#else
        for (int i = 0; i < data.Length; i++)
            _element[i * _Cols + col] = data[i];
#endif
    }

    /// <summary>
    /// 获取行
    /// </summary>
    /// <param name="row">行</param>
    /// <returns></returns>
    public double[] GetRows(int row)
    {
        var arr = new double[_Cols];
#if 永不执行___NET35
        Parallel.For(0, _Cols, j => {
            arr[j] = _element[row * _Cols + j];
        });
#else
        for (int j = 0; j < _Cols; j++)
            arr[j] = _element[row * _Cols + j];
#endif
        return arr;
    }

    /// <summary>
    /// 获取列
    /// </summary>
    /// <param name="col">列</param>
    /// <returns></returns>
    public double[] GetCols(int col)
    {
        var arr = new double[_Rows];
#if 永不执行___NET35
        Parallel.For(0, _Rows, i => {
            arr[i] = _element[i * _Cols + col];
        });
#else
        for (int i = 0; i < _Rows; i++)
            arr[i] = _element[i * _Cols + col];
#endif
        return arr;
    }

    /// <summary>
    /// 隔行赋值
    /// </summary>
    public Matrix DetachmentEvenLineOddLine()
    {
        // 拆离奇数行和偶数行
        var ret = Clone();
        // 将数组一分为二,然后上半部分隔行分配
        for (int i = 0; i < _Rows / 2; i++)// 0~3
            ret.SetRow(i * 2, GetRows(i));// 覆盖此行

        // 下半部分插入上半部分的奇数位置
        int v = 0;
        for (int i = _Rows / 2; i < _Rows; i++)// 4~7
        {
            ret.SetRow(v * 2 + 1, GetRows(i));// 覆盖此行 将4写入到1
            ++v;
        }
        return ret;
    }


    /// <summary>
    /// 矩阵分解(提高计算效率)
    /// </summary>
    /// <returns></returns>
    // public Matrix Lu()
    // {
    //    // A=L*U(L代表下三角矩阵,U代表上三角矩阵)
    //    this *
    //    return this;
    // }

    #endregion

    #region 转换对象
    /// <summary>
    /// 深拷贝
    /// </summary>
    /// <returns>返回深拷贝后的新对象</returns>
    public Matrix Clone()
    {
        var res = new Matrix(_Rows, _Cols);
#if 永不执行___NET35
        Parallel.For(0, _element.Length, i => {
            res._element[i] = _element[i];
        });
#else
        for (int i = 0; i < _element.Length; i++)
            res._element[i] = _element[i];
#endif
        return res;
    }
    public double[] ToArray()
    {
        var newDoubleArray = new double[_element.Length];
        _element.CopyTo(newDoubleArray, 0);
        return newDoubleArray;
    }

    public sealed override string ToString()
    {
        return ToString(null, null);
    }
    public string ToString(IFormatProvider? provider)
    {
        return ToString(null, provider);
    }
    public string ToString(string? format = null, IFormatProvider? formatProvider = null)
    {
        var str = new StringBuilder();

        for (int i = 0; i < _Rows; i++)
        {
            str.Append($"第{i}行:");
            str.Append('{');
            for (int j = 0; j < _Cols; j++)
            {
                str.Append(_element[i * Cols + j].ToString(format, formatProvider));
                if (j != _Cols - 1)
                    str.Append(";\t");
                else if (i != _Rows - 1)
                    str.Append("}" + Environment.NewLine);
            }
        }
        str.Append('}');
        return str.ToString();
    }

    // 隐式转换(相当于是重载赋值运算符)
    public static implicit operator Matrix(double[] array)
    {
        return new Matrix(array);
    }


#if CAD
    public static implicit operator Matrix(Matrix3d mat3d)
    {
        var arr = mat3d.ToArray();
        if (arr.Length != 16)
            throw new ArgumentException("转换失败Matrix3d数量不对");

        var newMatrix = new Matrix(4, 4);
        arr.CopyTo(newMatrix._element, 0);
        return newMatrix;
    }
#endif
    #endregion

    /// <summary>
    /// 交换行
    /// </summary>
    /// <param name="a">行1</param>
    /// <param name="b">行2</param>
    // public void ExchangeRow(int a, int b)
    // {
    //    // 先获取第a行和第b行
    //    int m_Cols = this._Cols;// 列
    //    var colList1 = new List<double>();
    //    for (int i = 0; i < m_Cols; i++)// 循环列
    //    {
    //        colList1.Add(this[a, i]);
    //    }
    //    for (int i = 0; i < m_Cols; i++)// 循环列
    //    {
    //        this[a, i] = this[b, i];
    //        this[b, i] = colList1[i];
    //    }
    // }
}
